package com.imooc.searchcountdown;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 每次请求都要创建新的线程池，执行完后销毁 应该使用单例的全局的后台线程池 参考App5
 *
 * @author ChangLiang
 * @date 2019/3/5
 */
public class App4 {

    private static Integer corePoolSize = 4;

    public static void main(String[] args) {

        List<String> list = new ArrayList<>();

        long start = System.currentTimeMillis();

        EsService esService = new EsService();

        ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("request-pool-%d").build();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                corePoolSize,
                10,
                0L,
                TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<>(20),
                threadFactory,
                new ThreadPoolExecutor.AbortPolicy()
        );

        // 创建4个futureTask
        FutureTask<String> itemsFutureTask = new FutureTask<>(() -> {
                String value;
                try {
                    Method method = esService.getClass().getDeclaredMethod("searchQueryItems", String.class);
                    Object returnValue = method.invoke(esService, "changliang");
                    value = returnValue != null ? returnValue.toString() : null;
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                    throw e;
                } catch (SecurityException e) {
                    e.printStackTrace();
                    throw e;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    throw e;
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                    throw e;
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                    throw e;
                }
                return value;
        });

        FutureTask<String> guidesFutureTask = new FutureTask<>(() -> {
                String value;
                try {
                    Method method = esService.getClass().getDeclaredMethod("searchQueryGuides", String.class);
                    Object returnValue = method.invoke(esService, "changliang");
                    value = returnValue != null ? returnValue.toString() : null;
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                    throw e;
                } catch (SecurityException e) {
                    e.printStackTrace();
                    throw e;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    throw e;
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                    throw e;
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                    throw e;
                }
                return value;
        });

        FutureTask<String> applicationsFutureTask = new FutureTask<>(() -> {
                String value;
                try {
                    Method method = esService.getClass().getDeclaredMethod("getApplications", String.class);
                    Object returnValue = method.invoke(esService, "changliang");
                    value = returnValue != null ? returnValue.toString() : null;
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                    throw e;
                } catch (SecurityException e) {
                    e.printStackTrace();
                    throw e;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    throw e;
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                    throw e;
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                    throw e;
                }
                return value;
        });

        FutureTask<String> appointsFutureTask = new FutureTask<>(() -> {
                String value;
                try {
                    Method method = esService.getClass().getDeclaredMethod("getAppointItems", String.class);
                    Object returnValue = method.invoke(esService, "changliang");
                    value = returnValue != null ? returnValue.toString() : null;
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                    throw e;
                } catch (SecurityException e) {
                    e.printStackTrace();
                    throw e;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    throw e;
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                    throw e;
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                    throw e;
                }
                return value;
        });

        // 用4个线程来执行
        threadPoolExecutor.execute(itemsFutureTask);
        threadPoolExecutor.execute(guidesFutureTask);
        threadPoolExecutor.execute(applicationsFutureTask);
        threadPoolExecutor.execute(appointsFutureTask);

        // 初始化返回值
        String items = null;
        String guides = null;
        String applications = null;
        String appoints = null;

        // 赋值
        try {
            items = itemsFutureTask.get(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            itemsFutureTask.cancel(true);
            System.out.println("itemsFutureTask.get 方法执行中断");
        } catch (ExecutionException e) {
            itemsFutureTask.cancel(true);
            System.out.println("itemsFutureTask.get Execution异常");
        } catch (TimeoutException e) {
            itemsFutureTask.cancel(true);
            System.out.println("itemsFutureTask.get invoke timeout");
        }
        if (items != null) {
            list.add(items);
        }
        try {
            guides = guidesFutureTask.get(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            guidesFutureTask.cancel(true);
            System.out.println("guidesFutureTask.get 方法执行中断");
        } catch (ExecutionException e) {
            guidesFutureTask.cancel(true);
            System.out.println("guidesFutureTask.get Execution异常");
        } catch (TimeoutException e) {
            guidesFutureTask.cancel(true);
            System.out.println("guidesFutureTask.get invoke timeout");
        }
        if (guides != null) {
            list.add(guides);
        }
        try {
            applications = applicationsFutureTask.get(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            applicationsFutureTask.cancel(true);
            System.out.println("applicationsFutureTask.get 方法执行中断");
        } catch (ExecutionException e) {
            applicationsFutureTask.cancel(true);
            System.out.println("applicationsFutureTask.get Execution异常");
        } catch (TimeoutException e) {
            applicationsFutureTask.cancel(true);
            System.out.println("applicationsFutureTask.get invoke timeout");
        }
        if (applications != null) {
            list.add(applications);
        }
        try {
            appoints = appointsFutureTask.get(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            appointsFutureTask.cancel(true);
            System.out.println("appointsFutureTask.get 方法执行中断");
        } catch (ExecutionException e) {
            appointsFutureTask.cancel(true);
            System.out.println("appointsFutureTask.get Execution异常");
        } catch (TimeoutException e) {
            appointsFutureTask.cancel(true);
            System.out.println("appointsFutureTask.get invoke timeout");
        }
        if (appoints != null) {
            list.add(appoints);
        }

        long end = System.currentTimeMillis();

        System.out.println((end - start));
        System.out.println(list);
    }
}
